/**
 * Copyright (C) 2010, 2011 Neofonie GmbH
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package eu.dicodeproject.blogimport.filereader;

import java.io.File;
import java.io.IOException;

import javax.xml.stream.XMLStreamException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sadun.util.polling.DirectoryPoller;

/**
 * A reader that polls a directory in the file system for documents. It is
 * configured with the following parameters:
 * <ul>
 * <li><code>PollingInterval</code> (1000ms) - directory scanner polling
 * interval</li>
 * </ul>
 * 
 */
public class PollingFileSystemReader {

	private static final Logger LOG = LoggerFactory.getLogger(PollingFileSystemReader.class);

	private int pollInterval = 1000;

	private DirectoryPoller directoryPoller;
	
	private BlogImporterPollManager pollingManager;

	private PollingMutex monitor = new PollingMutex();

	/**
	 * This method initializes the reader with the referenced input directory as absolute path.
	 * 
	 * @param inputDir the absolute path to the input directory for this reader
	 */
	public void initialize(String inputDir, String automoveDir) {
		File directory = new File(inputDir);
		
		// if input directory does not exist or is not a directory, throw
		// exception
		if (!directory.exists() || !directory.isDirectory()) {
			LOG.error("No directory exists, or is no directory (" + directory + ").");
		}

		File automoveDirectory = null;
		if (automoveDir != null) {
			automoveDirectory = new File(automoveDir);
			if (!automoveDirectory.exists() || !automoveDirectory.isDirectory()) {
				LOG.error("Automove directory does not exist, or is no directory (" + automoveDirectory + ").");
				automoveDirectory = null;
			}
		}
		
		// create and start the polling thread
		this.directoryPoller = new DirectoryPoller(directory);
		this.directoryPoller.setAutoMove(true);
		if (automoveDirectory != null) {
			this.directoryPoller.setAutoMoveDirectory(directory, automoveDirectory);
		}
		this.directoryPoller.setBypassLockedFiles(true);
		this.directoryPoller.setPollInterval(this.pollInterval);
		this.pollingManager = new BlogImporterPollManager(); 
		this.pollingManager.setMonitor(this.monitor);
    this.directoryPoller.addPollManager(this.pollingManager);
		this.directoryPoller.start();
	}

	/**
	 * Never returns false and blocks, as we want to poll until new files are
	 * available.
	 * 
	 * @return true
	 */
	public boolean hasNext() {	   
	  if (!this.pollingManager.getFileQueue().isEmpty()) {
			return true;
		}

		try {
			synchronized (this.monitor) {
				this.monitor.setLock(true);
				LOG.info("No files available in queue, waiting for polling thread notification.");
				while (this.monitor.isLock()) {
					LOG.debug("Waitcycle...");
					this.monitor.wait(5000);
				}
				LOG.info("Notified, waking up.");
				return true;
			}
		} catch (InterruptedException ire) {
			LOG.error("Interuptions occured", ire);
			// Restore the interrupted status
			Thread.currentThread().interrupt();
			throw new RuntimeException("Interruption occured", ire);
		}
	}

	/**
	 * Looks for the next file in the queue.
	 * 
	 * @return
	 * @throws IOException
	 * @throws XMLStreamException
	 * @throws InterruptedException 
	 */
	public File getNext() throws IOException, XMLStreamException, InterruptedException {

		// get next file from Queue
		File file = null;
		file = this.pollingManager.getFileQueue().take();		
    if (LOG.isInfoEnabled()) {
    	LOG.debug("Queue size "+ this.pollingManager.getFileQueue().size() +". Retrieved next file from queue. " + file);
    }
		return file;
	}

	/**
	 * Shutdown the reader.
	 * 
	 * @throws IOException
	 */
	public void close() throws IOException {
		if (LOG.isInfoEnabled()) {
			LOG.info("Shutting down directoryPoller");
		}
		if (!this.directoryPoller.isShuttingDown()) {
			this.directoryPoller.shutdown();
		}
	}

}
